package kycadminrepo

import (
	"context"
	"time"

	new_admin "code.bydev.io/cht/customer/kyc-stub.git/pkg/bybit/kyc/admin/v1"
	"code.bydev.io/cht/customer/kyc_admin_service/internal/pkg/kycadminapi/dto"
	"code.bydev.io/cht/customer/kyc_dbstructure.git/pkg/o_kyc_country_config"
	"emperror.dev/errors"
	"git.bybit.com/svc/go/pkg/bdal"
	"git.bybit.com/svc/go/pkg/bdal/bqb"
	jsoniter "github.com/json-iterator/go"
	"go.uber.org/zap"
)

func (r *repo) GetCountryConfigList(ctx context.Context, condition *dto.CountrySearchCondition) ([]*o_kyc_country_config.Record, int, error) {
	var records []*o_kyc_country_config.Record
	// 拼接where条件
	var fns []bqb.Condition
	var argsMapm = make(bqb.Args)

	r.logger.Info("GetCountryConfigList", zap.Any("condition", condition))

	pool, err := r.kycDB.DBDefaultReplicaNodePool(ctx)
	if err != nil {
		r.logger.Error("GetDBPoolFail", zap.Error(err), zap.Reflect("condition", condition))
		return nil, 0, err
	}

	// 组装查询条件
	if condition.CountryCode != "" {
		fns = append(fns, func(wb *bqb.WhereBuilder) {
			o_kyc_country_config.FldCountryCode.EQ(wb)
		})
		argsMapm[o_kyc_country_config.FldCountryCode.Param()] = condition.CountryCode
	}

	if condition.CountryName != "" {
		fns = append(fns, func(wb *bqb.WhereBuilder) {
			o_kyc_country_config.FldCountryName.EQ(wb)
		})
		argsMapm[o_kyc_country_config.FldCountryName.Param()] = condition.CountryName
	}

	sqlCnt := o_kyc_country_config.Count().WhereC(fns...).LimitC(1).SQL()
	total, errCnt := bdal.ScanInt(sqlCnt.QueryArgs(ctx, pool, argsMapm))
	if errCnt != nil {
		r.logger.Error("CountCountryConfigFailed", zap.Error(err), zap.Reflect("condition", condition))
		return nil, 0, errCnt
	}

	oft := condition.PageSize * (condition.PageNo - 1)
	slt := o_kyc_country_config.Select()
	slt.Limit(int(condition.PageSize))

	if condition.CountryCode == "" && condition.CountryName == "" {
		slt.Offset(int(oft) + 1)
		total--
	}

	sqlSlt := slt.WhereC(fns...).OrderByC(o_kyc_country_config.FldId, bqb.ASC).SQL()

	records, err = o_kyc_country_config.ScanRecords(sqlSlt.QueryArgs(ctx, pool, argsMapm))
	if err != nil {
		r.logger.Error("SearchCountryConfigsFail", zap.Error(err), zap.Reflect("condition", condition))
		return nil, 0, err
	}

	return records, total, nil
}

func (r *repo) SetCountryConfig(ctx context.Context, config *o_kyc_country_config.Record) error {
	r.logger.Info("SetCountryConfig", zap.Any("config", config))

	pool, err := r.kycDB.DBDefaultMasterNodePool(ctx)
	if err != nil {
		r.logger.Error("GetDBPoolFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	sql := o_kyc_country_config.Select().WhereC(func(wb *bqb.WhereBuilder) {
		o_kyc_country_config.FldCountryCode.EQ(wb)
	}).LimitC(1).SQL()

	record, err := o_kyc_country_config.ScanRecordNil(sql.QueryArgs(ctx, pool, bqb.Args{
		o_kyc_country_config.FldCountryCode.Param(): config.CountryCode}))
	if err != nil {
		r.logger.Error("ScanRecordFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	if record == nil {
		config.CreatedAt = time.Now()
		err = config.Insert(ctx, pool)
	} else {
		config.Id = record.Id
		config.CreatedAt = record.CreatedAt
		_, err = config.Update(ctx, pool)
	}

	if err != nil {
		r.logger.Error("SetRecordFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	return nil
}

func (r *repo) GetDocSubtypeConfig(ctx context.Context) (*new_admin.DocSubtype, error) {
	r.logger.Info("GetDocSubtypeConfig")
	pool, err := r.kycDB.DBDefaultMasterNodePool(ctx)
	if err != nil {
		r.logger.Error("GetDBPoolFail", zap.Error(err))
		return nil, err
	}

	sql := o_kyc_country_config.Select().WhereC(func(wb *bqb.WhereBuilder) {
		o_kyc_country_config.FldCountryCode.EQ(wb)
	}).LimitC(1).SQL()

	record, err := o_kyc_country_config.ScanRecordNil(sql.QueryArgs(ctx, pool, bqb.Args{
		o_kyc_country_config.FldCountryCode.Param(): "common"}))
	if err != nil {
		r.logger.Error("ScanRecordFail", zap.Error(err))
		return nil, err
	}

	if record == nil {
		r.logger.Error("CommonConfigRecord not exist")
		return nil, errors.New("CommonConfigRecord not exist")
	}

	originCommonConfig := &dto.CommonConfig{}
	err = jsoniter.Unmarshal([]byte(record.ExtraData.String), originCommonConfig)
	if err != nil {
		r.logger.Error("UnmarshalFail", zap.Error(err))
		return nil, err
	}

	return originCommonConfig.DocSubtype, nil
}

func (r *repo) SetDocSubtypeConfig(ctx context.Context, config *new_admin.DocSubtype) error {
	r.logger.Info("SetCommonConfig", zap.Any("config", config))

	pool, err := r.kycDB.DBDefaultMasterNodePool(ctx)
	if err != nil {
		r.logger.Error("GetDBPoolFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	sql := o_kyc_country_config.Select().WhereC(func(wb *bqb.WhereBuilder) {
		o_kyc_country_config.FldCountryCode.EQ(wb)
	}).LimitC(1).SQL()

	record, err := o_kyc_country_config.ScanRecordNil(sql.QueryArgs(ctx, pool, bqb.Args{
		o_kyc_country_config.FldCountryCode.Param(): "common"}))
	if err != nil {
		r.logger.Error("ScanRecordFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	if record == nil {
		r.logger.Error("CommonConfigRecord not exist", zap.Reflect("config", config))
		return errors.New("CommonConfigRecord not exist")
	}

	originCommonConfig := &dto.CommonConfig{}
	err = jsoniter.Unmarshal([]byte(record.ExtraData.String), originCommonConfig)
	if err != nil {
		r.logger.Error("UnmarshalFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	// 目前只能设置证件子类型
	originCommonConfig.DocSubtype = config
	newCommonConfig, err := jsoniter.Marshal(originCommonConfig)
	if err != nil {
		r.logger.Error("MarshalFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	record.ExtraData.String = string(newCommonConfig)
	_, err = record.Update(ctx, pool)
	if err != nil {
		r.logger.Error("UpdateRecordFail", zap.Error(err), zap.Reflect("config", config))
		return err
	}

	return nil
}
